home *** CD-ROM | disk | FTP | other *** search
/ PC go! 2018 January / PCgo 01-2018 CD-ROM Germany.iso / nw.pak / Unnamed File 005237.txt < prev    next >
Encoding:
Text File  |  2015-07-29  |  14.2 KB  |  390 lines

  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4.  
  5. 'use strict';
  6.  
  7. privateScriptController.installClass('HTMLMarqueeElement', function(HTMLMarqueeElementPrototype) {
  8.  
  9.     var kDefaultScrollAmount = 6;
  10.     var kDefaultScrollDelayMS = 85;
  11.     var kMinimumScrollDelayMS = 60;
  12.  
  13.     var kDefaultLoopLimit = -1;
  14.  
  15.     var kBehaviorScroll = 'scroll';
  16.     var kBehaviorSlide = 'slide';
  17.     var kBehaviorAlternate = 'alternate';
  18.  
  19.     var kDirectionLeft = 'left';
  20.     var kDirectionRight = 'right';
  21.     var kDirectionUp = 'up';
  22.     var kDirectionDown = 'down';
  23.  
  24.     var kPresentationalAttributes = [
  25.         'bgcolor',
  26.         'height',
  27.         'hspace',
  28.         'vspace',
  29.         'width',
  30.     ];
  31.  
  32.     function convertHTMLLengthToCSSLength(value) {
  33.         var match = value.match(/^\s*([\d.]+)(%)?\s*/);
  34.         if (match)
  35.             return match[2] === '%' ? match[1] + '%' : match[1] + 'px';
  36.         return null;
  37.     }
  38.  
  39.     // FIXME: Consider moving these utility functions to PrivateScriptRunner.js.
  40.     var kInt32Max = Math.pow(2, 31);
  41.  
  42.     function convertToLong(n) {
  43.         // Using parseInt() is wrong but this aligns with the existing behavior of StringImpl::toInt().
  44.         // FIXME: Implement a correct algorithm of the Web IDL value conversion.
  45.         var value = parseInt(n);
  46.         if (!isNaN(value) && -kInt32Max <= value && value < kInt32Max)
  47.             return value;
  48.         return NaN;
  49.     }
  50.  
  51.     function reflectAttribute(prototype, attributeName, propertyName) {
  52.         Object.defineProperty(prototype, propertyName, {
  53.             get: function() {
  54.                 return this.getAttribute(attributeName) || '';
  55.             },
  56.             set: function(value) {
  57.                 this.setAttribute(attributeName, value);
  58.             },
  59.             configurable: true,
  60.             enumerable: true,
  61.         });
  62.     }
  63.  
  64.     function reflectBooleanAttribute(prototype, attributeName, propertyName) {
  65.         Object.defineProperty(prototype, propertyName, {
  66.             get: function() {
  67.                 return this.getAttribute(attributeName);
  68.             },
  69.             set: function(value) {
  70.                 if (value)
  71.                     this.setAttribute(attributeName, '');
  72.                 else
  73.                     this.removeAttribute(attributeName);
  74.             },
  75.         });
  76.     }
  77.  
  78.     reflectAttribute(HTMLMarqueeElementPrototype, 'behavior', 'behavior');
  79.     reflectAttribute(HTMLMarqueeElementPrototype, 'bgcolor', 'bgColor');
  80.     reflectAttribute(HTMLMarqueeElementPrototype, 'direction', 'direction');
  81.     reflectAttribute(HTMLMarqueeElementPrototype, 'height', 'height');
  82.     reflectAttribute(HTMLMarqueeElementPrototype, 'hspace', 'hspace');
  83.     reflectAttribute(HTMLMarqueeElementPrototype, 'vspace', 'vspace');
  84.     reflectAttribute(HTMLMarqueeElementPrototype, 'width', 'width');
  85.     reflectBooleanAttribute(HTMLMarqueeElementPrototype, 'truespeed', 'trueSpeed');
  86.  
  87.     HTMLMarqueeElementPrototype.createdCallback = function() {
  88.         var shadow = this.createShadowRoot();
  89.         var style = document.createElement('style');
  90.         style.textContent = ':host { display: inline-block; width: -webkit-fill-available; overflow: hidden; text-align: initial; white-space: nowrap; }'
  91.             + ':host([direction="up"]), :host([direction="down"]) { overflow: initial; overflow-y: hidden; white-space: initial; }';
  92.         shadow.appendChild(style);
  93.  
  94.         var mover = document.createElement('div');
  95.         shadow.appendChild(mover);
  96.  
  97.         mover.appendChild(document.createElement('content'));
  98.  
  99.         this.loopCount_ = 0;
  100.         this.mover_ = mover;
  101.         this.player_ = null;
  102.         this.continueCallback_ = null;
  103.     };
  104.  
  105.     HTMLMarqueeElementPrototype.attachedCallback = function() {
  106.         for (var i = 0; i < kPresentationalAttributes.length; ++i) {
  107.             this.initializeAttribute_(kPresentationalAttributes[i]);
  108.         }
  109.  
  110.         this.start();
  111.     };
  112.  
  113.     HTMLMarqueeElementPrototype.detachedCallback = function() {
  114.         this.stop();
  115.     };
  116.  
  117.     HTMLMarqueeElementPrototype.attributeChangedCallback = function(name, oldValue, newValue) {
  118.         switch (name) {
  119.         case 'bgcolor':
  120.             this.style.backgroundColor = newValue;
  121.             break;
  122.         case 'height':
  123.             this.style.height = convertHTMLLengthToCSSLength(newValue);
  124.             break;
  125.         case 'hspace':
  126.             var margin = convertHTMLLengthToCSSLength(newValue);
  127.             this.style.marginLeft = margin;
  128.             this.style.marginRight = margin;
  129.             break;
  130.         case 'vspace':
  131.             var margin = convertHTMLLengthToCSSLength(newValue);
  132.             this.style.marginTop = margin;
  133.             this.style.marginBottom = margin;
  134.             break;
  135.         case 'width':
  136.             this.style.width = convertHTMLLengthToCSSLength(newValue);
  137.             break;
  138.         case 'behavior':
  139.         case 'direction':
  140.         case 'loop':
  141.         case 'scrollAmount':
  142.         case 'scrollDelay':
  143.         case 'trueSpeed':
  144.             // FIXME: Not implemented.
  145.             break;
  146.         }
  147.     };
  148.  
  149.     HTMLMarqueeElementPrototype.initializeAttribute_ = function(name) {
  150.         var value = this.getAttribute(name);
  151.         if (value === null)
  152.             return;
  153.         this.attributeChangedCallback(name, null, value);
  154.     };
  155.  
  156.     Object.defineProperty(HTMLMarqueeElementPrototype, 'scrollAmount', {
  157.         get: function() {
  158.             var value = this.getAttribute('scrollamount');
  159.             var scrollAmount = convertToLong(value);
  160.             if (isNaN(scrollAmount) || scrollAmount < 0)
  161.                 return kDefaultScrollAmount;
  162.             return scrollAmount;
  163.         },
  164.         set: function(value) {
  165.             if (value < 0)
  166.                 privateScriptController.throwException(privateScriptController.DOMException.IndexSizeError, "The provided value (" + value + ") is negative.");
  167.             this.setAttribute('scrollamount', value);
  168.         },
  169.     });
  170.  
  171.     Object.defineProperty(HTMLMarqueeElementPrototype, 'scrollDelay', {
  172.         get: function() {
  173.             var value = this.getAttribute('scrolldelay');
  174.             var scrollDelay = convertToLong(value);
  175.             if (isNaN(scrollDelay) || scrollDelay < 0)
  176.                 return kDefaultScrollDelayMS;
  177.             return scrollDelay;
  178.         },
  179.         set: function(value) {
  180.             if (value < 0)
  181.                 privateScriptController.throwException(privateScriptController.DOMException.IndexSizeError, "The provided value (" + value + ") is negative.");
  182.             this.setAttribute('scrolldelay', value);
  183.         },
  184.     });
  185.  
  186.     Object.defineProperty(HTMLMarqueeElementPrototype, 'loop', {
  187.         get: function() {
  188.             var value = this.getAttribute('loop');
  189.             var loop = convertToLong(value);
  190.             if (isNaN(loop) || loop <= 0)
  191.                 return kDefaultLoopLimit;
  192.             return loop;
  193.         },
  194.         set: function(value) {
  195.             if (value <= 0 && value != -1)
  196.                 privateScriptController.throwException(privateScriptController.DOMException.IndexSizeError, "The provided value (" + value + ") is neither positive nor -1.");
  197.             this.setAttribute('loop', value);
  198.         },
  199.     });
  200.  
  201.     HTMLMarqueeElementPrototype.getGetMetrics_ = function() {
  202.         if (this.direction === 'up' || this.direction === 'down')
  203.             this.mover_.style.height = '-webkit-max-content';
  204.         else
  205.             this.mover_.style.width = '-webkit-max-content';
  206.  
  207.         var moverStyle = getComputedStyle(this.mover_);
  208.         var marqueeStyle = getComputedStyle(this);
  209.  
  210.         var metrics = {};
  211.         metrics.contentWidth = parseInt(moverStyle.width);
  212.         metrics.contentHeight = parseInt(moverStyle.height);
  213.         metrics.marqueeWidth = parseInt(marqueeStyle.width);
  214.         metrics.marqueeHeight = parseInt(marqueeStyle.height);
  215.  
  216.         if (this.direction === 'up' || this.direction === 'down')
  217.             this.mover_.style.height = '';
  218.         else
  219.             this.mover_.style.width = '';
  220.         return metrics;
  221.     };
  222.  
  223.     HTMLMarqueeElementPrototype.getAnimationParameters_ = function() {
  224.         var metrics = this.getGetMetrics_();
  225.  
  226.         var totalWidth = metrics.marqueeWidth + metrics.contentWidth;
  227.         var totalHeight = metrics.marqueeHeight + metrics.contentHeight;
  228.  
  229.         var innerWidth = metrics.marqueeWidth - metrics.contentWidth;
  230.         var innerHeight = metrics.marqueeHeight - metrics.contentHeight;
  231.  
  232.         var parameters = {};
  233.  
  234.         switch (this.behavior) {
  235.         case kBehaviorScroll:
  236.         default:
  237.             switch (this.direction) {
  238.             case kDirectionLeft:
  239.             default:
  240.                 parameters.transformBegin = 'translateX(' + metrics.marqueeWidth + 'px)';
  241.                 parameters.transformEnd = 'translateX(-' + metrics.contentWidth + 'px)';
  242.                 parameters.distance = totalWidth;
  243.                 break;
  244.             case kDirectionRight:
  245.                 parameters.transformBegin = 'translateX(-' + metrics.contentWidth + 'px)';
  246.                 parameters.transformEnd = 'translateX(' + metrics.marqueeWidth + 'px)';
  247.                 parameters.distance = totalWidth;
  248.                 break;
  249.             case kDirectionUp:
  250.                 parameters.transformBegin = 'translateY(' + metrics.marqueeHeight + 'px)';
  251.                 parameters.transformEnd = 'translateY(-' + metrics.contentHeight + 'px)';
  252.                 parameters.distance = totalHeight;
  253.                 break;
  254.             case kDirectionDown:
  255.                 parameters.transformBegin = 'translateY(-' + metrics.contentHeight + 'px)';
  256.                 parameters.transformEnd = 'translateY(' + metrics.marqueeHeight + 'px)';
  257.                 parameters.distance = totalHeight;
  258.                 break;
  259.             }
  260.             break;
  261.         case kBehaviorAlternate:
  262.             switch (this.direction) {
  263.             case kDirectionLeft:
  264.             default:
  265.                 parameters.transformBegin = 'translateX(' + innerWidth + 'px)';
  266.                 parameters.transformEnd = 'translateX(0)';
  267.                 parameters.distance = innerWidth;
  268.                 break;
  269.             case kDirectionRight:
  270.                 parameters.transformBegin = 'translateX(0)';
  271.                 parameters.transformEnd = 'translateX(' + innerWidth + 'px)';
  272.                 parameters.distance = innerWidth;
  273.                 break;
  274.             case kDirectionUp:
  275.                 parameters.transformBegin = 'translateY(' + innerHeight + 'px)';
  276.                 parameters.transformEnd = 'translateY(0)';
  277.                 parameters.distance = innerHeight;
  278.                 break;
  279.             case kDirectionDown:
  280.                 parameters.transformBegin = 'translateY(0)';
  281.                 parameters.transformEnd = 'translateY(' + innerHeight + 'px)';
  282.                 parameters.distance = innerHeight;
  283.                 break;
  284.             }
  285.  
  286.             if (this.loopCount_ % 2) {
  287.                 var transform = parameters.transformBegin;
  288.                 parameters.transformBegin = parameters.transformEnd;
  289.                 parameters.transformEnd = transform;
  290.             }
  291.  
  292.             break;
  293.         case kBehaviorSlide:
  294.             switch (this.direction) {
  295.             case kDirectionLeft:
  296.             default:
  297.                 parameters.transformBegin = 'translateX(' + metrics.marqueeWidth + 'px)';
  298.                 parameters.transformEnd = 'translateX(0)';
  299.                 parameters.distance = metrics.marqueeWidth;
  300.                 break;
  301.             case kDirectionRight:
  302.                 parameters.transformBegin = 'translateX(-' + metrics.contentWidth + 'px)';
  303.                 parameters.transformEnd = 'translateX(' + innerWidth + 'px)';
  304.                 parameters.distance = metrics.marqueeWidth;
  305.                 break;
  306.             case kDirectionUp:
  307.                 parameters.transformBegin = 'translateY(' + metrics.marqueeHeight + 'px)';
  308.                 parameters.transformEnd = 'translateY(0)';
  309.                 parameters.distance = metrics.marqueeHeight;
  310.                 break;
  311.             case kDirectionDown:
  312.                 parameters.transformBegin = 'translateY(-' + metrics.contentHeight + 'px)';
  313.                 parameters.transformEnd = 'translateY(' + innerHeight + 'px)';
  314.                 parameters.distance = metrics.marqueeHeight;
  315.                 break;
  316.             }
  317.             break;
  318.         }
  319.  
  320.         return parameters
  321.     };
  322.  
  323.     function animationFinished_(event) {
  324.         var player = event.target;
  325.         var marquee = player.marquee_;
  326.         marquee.loopCount_++;
  327.         marquee.start();
  328.     };
  329.  
  330.     HTMLMarqueeElementPrototype.shouldContinue_ = function() {
  331.         var loop = this.loop;
  332.  
  333.         // By default, slide loops only once.
  334.         if (loop <= 0 && this.behavior === kBehaviorSlide)
  335.             loop = 1;
  336.  
  337.         if (loop <= 0)
  338.             return true;
  339.         return this.loopCount_ < loop;
  340.     };
  341.  
  342.     HTMLMarqueeElementPrototype.continue_ = function() {
  343.         if (!this.shouldContinue_()) {
  344.             return;
  345.         }
  346.  
  347.         if (this.player_ && this.player_.playState === 'paused') {
  348.             this.player_.play();
  349.             return;
  350.         }
  351.  
  352.         var parameters = this.getAnimationParameters_();
  353.         var scrollDelay = this.scrollDelay;
  354.         if (scrollDelay < kMinimumScrollDelayMS && !this.trueSpeed)
  355.             scrollDelay = kDefaultScrollDelayMS;
  356.         var player = this.mover_.animate([
  357.             { transform: parameters.transformBegin },
  358.             { transform: parameters.transformEnd },
  359.         ], {
  360.             duration: this.scrollAmount == 0 ? 0 : parameters.distance * scrollDelay / this.scrollAmount,
  361.             fill: 'forwards',
  362.         });
  363.         player.marquee_ = this;
  364.         player.onfinish = animationFinished_;
  365.  
  366.         this.player_ = player;
  367.     };
  368.  
  369.     HTMLMarqueeElementPrototype.start = function() {
  370.         if (this.continueCallback_)
  371.             return;
  372.         this.continueCallback_ = requestAnimationFrame(function() {
  373.             this.continueCallback_ = null;
  374.             this.continue_();
  375.         }.bind(this));
  376.     };
  377.  
  378.     HTMLMarqueeElementPrototype.stop = function() {
  379.         if (this.continueCallback_) {
  380.             cancelAnimationFrame(this.continueCallback_);
  381.             this.continueCallback_ = null;
  382.             return;
  383.         }
  384.  
  385.         if (this.player_) {
  386.             this.player_.pause();
  387.         }
  388.     };
  389. });
  390.